// half-page/index.js
import {
  GestureState,
  lerp,
  clamp,
  Curves,
} from '../../utils/custom-route/util'

function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}

const {
  timing
} = wx.worklet

const {
  windowHeight
} = getApp().globalData;

Page({
  data: {
    wifiList: [], // 用于存储获取到的WiFi信息列表
    wifiInfo: {},
    devices: [],
    chs: [],
    devName: '',
    devMac: '',
    wifiName: '',
    wifiPwd: '',
    serverIp: '120.78.129.226',
    serverTcpPort: '4476',
    serverHttpPort: '4476',
    serverMask: '',
    serverInfo: {},
    createBLEErrorCount: 1
  },
  onLoad(options) {
    this.setNavigationBarColor()

    // 获取用户上次输入的信息
    this.getLastTimeInputInfo()

    //  处理数据
    this.devName = options.name
    this.devMac = options.deviceId
    console.log(options);
  },

  onUnload() {
    this.resetNavigationBarColor()
  },

  shouldPanResponse() {
    'worklet';
    return this.startPan.value;
  },
  shouldScrollViewResponse(pointerEvent) {
    'worklet';
    const {
      primaryAnimation
    } = this.customRouteContext;
    if (primaryAnimation.value < 1) return false;
    const scrollTop = this.scrollTop.value;
    const {
      deltaY
    } = pointerEvent;
    const result = !(scrollTop <= 0 && deltaY > 0);
    this.startPan.value = !result;
    return result;
  },
  adjustDecelerationVelocity(velocity) {
    'worklet';
    const scrollTop = this.scrollTop.value;
    return scrollTop <= 0 ? 0 : velocity;
  },
  handleScroll(evt) {
    'worklet';
    this.scrollTop.value = evt.detail.scrollTop;
  },
  handleDragStart() {
    'worklet';
    this.startPan.value = true;
    const {
      startUserGesture
    } = this.customRouteContext;
    startUserGesture();
  },

  handleDragUpdate(delta) {
    'worklet';
    const {
      primaryAnimation
    } = this.customRouteContext;
    const newVal = primaryAnimation.value - delta;
    primaryAnimation.value = clamp(newVal, 0.0, 1.0);
  },

  handleDragEnd(velocity) {
    'worklet';
    this.startPan.value = false;
    const {
      primaryAnimation,
      stopUserGesture,
      didPop
    } = this.customRouteContext;

    let animateForward = false;
    if (Math.abs(velocity) >= 1) {
      animateForward = velocity <= 0;
    } else {
      animateForward = primaryAnimation.value > 0.7;
    }
    const t = primaryAnimation.value;
    const animationCurve = Curves.fastLinearToSlowEaseIn;
    if (animateForward) {
      const droppedPageForwardAnimationTime = Math.min(
        Math.floor(lerp(300, 0, t)),
        300,
      );
      primaryAnimation.value = timing(
        1.0, {
          duration: droppedPageForwardAnimationTime,
          easing: animationCurve,
        },
        () => {
          'worklet'
          stopUserGesture();
        },
      );
    } else {
      const droppedPageBackAnimationTime = Math.floor(lerp(0, 300, t));
      primaryAnimation.value = timing(
        0.0, {
          duration: droppedPageBackAnimationTime,
          easing: animationCurve,
        },
        () => {
          'worklet'
          stopUserGesture();
          didPop();
        },
      );
    }
  },

  handleVerticalDrag(evt) {
    'worklet';
    if (evt.state === GestureState.BEGIN) {
      this.handleDragStart();
    } else if (evt.state === GestureState.ACTIVE) {
      const delta = evt.deltaY / windowHeight;
      this.handleDragUpdate(delta);
    } else if (evt.state === GestureState.END) {
      const velocity = evt.velocityY / windowHeight;
      this.handleDragEnd(velocity);
    } else if (evt.state === GestureState.CANCELLED) {
      this.handleDragEnd(0.0);
    }
  },

  setNavigationBarColor() {
    wx.setNavigationBarColor({
      frontColor: '#ffffff',
      backgroundColor: '#000000',
      duration: 300,
    });
  },

  resetNavigationBarColor() {
    wx.setNavigationBarColor({
      frontColor: '#000000',
      backgroundColor: '#ffffff',
      duration: 300,
    });
  },

  back() {
    wx.navigateBack({
      delta: 1,
    });
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  },
  initStartWifi() {
    let _this = this
    wx.startWifi({
      success(res) {
        // 获取wifi列表
        _this.getWifiList()
        console.log('开始获取wifi列表');
      },
      fail() {
        wx.showToast({
          title: '初始化wifi失败',
          icon: 'error',
          duration: 2000
        })
      }
    })
  },
  getWifiList() {
    let _this = this
    wx.getWifiList({
      success: (res) => {
        wx.onGetWifiList((wifi) => {
          console.log("获取到 Wi-Fi 列表");
          wx.showToast({
            title: '成功',
            icon: 'success',
            duration: 2000
          })
          // 这里可以将 wifi 存储到 data 中，然后在页面中展示出来
          // console.log(wifi.wifiList);
          let wifiSSIDSet = new Set()
          let wifiList = []
          wifi.wifiList.forEach(t => {
            if (!wifiSSIDSet.has(t.SSID)) {
              wifiSSIDSet.add(t.SSID)
              wifiList.push(t)
            }
          })
          console.log(wifiList);
          this.setData({
            wifiList: wifiList
          })
        });
      },
      fail: (res) => {
        wx.showToast({
          title: '没有WiFi权限',
          icon: 'error',
          duration: 2000
        })
      }
    })
  },
  getWifiAuth() {
    wx.showToast({
      title: '正在加载...',
      icon: 'loading',
      duration: 2000
    })
    let _this = this
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.userLocation']) {
          wx.authorize({
            scope: 'scope.userLocation',
            success() {
              wx.showToast({
                title: '申请定位权限成功',
                icon: 'success',
                duration: 2000
              })
              _this.initStartWifi()
            },
            fail(e) {
              wx.showToast({
                title: '申请定位权限失败',
                icon: 'error',
                duration: 2000
              })
            }
          })
        } else {
          console.log('已有定位权限');
          _this.initStartWifi()
        }
      },
      fail(e) {
        wx.showToast({
          title: '获取用户授权权限失败',
          icon: 'error',
          duration: 2000
        })
      }
    })
  },
  setWifiInfo(e) {
    if (this.wifiName != e.currentTarget.dataset.wifiname) {
      this.wifiName = e.currentTarget.dataset.wifiname
      this.setData({
        wifiName: this.wifiName
      })
    }
  },
  createBLEConnection(dataInfo) {
    const deviceId = this.devMac
    const name = this.devName
    let _this = this
    wx.showToast({
      title: '正在创建连接',
      icon: 'loading',
      duration: 2000
    })
    wx.createBLEConnection({
      deviceId,
      success: (res) => {
        this.setData({
          connected: true,
          name,
          deviceId,
        })
        this.getBLEDeviceServices(deviceId, dataInfo)
      },
      fail(e) {
        if (_this.data.createBLEErrorCount < 4) {
          wx.showToast({
            title: ('连接丢失重试' + _this.data.createBLEErrorCount),
            icon: 'loading',
            duration: 2000
          })
          setTimeout(function () {
            // 在这里写要延迟执行的代码
            _this.data.createBLEErrorCount++
            _this.createBLEConnection(dataInfo)
          }, 2000);
        } else {
          _this.errorResult('检查蓝牙状态')
          _this.data.createBLEErrorCount = 1
        }
      }
    })
  },
  getBLEDeviceServices(deviceId, dataInfo) {
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid, dataInfo)
            return
          }
        }
      }
    })
  },
  getBLEDeviceCharacteristics(deviceId, serviceId, dataInfo) {
    console.log('serviceId');
    console.log(serviceId);
    wx.showToast({
      title: '正在写入数据',
      icon: 'loading',
      duration: 2000
    })
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        console.log('getBLEDeviceCharacteristics success', res.characteristics)
        // dataInfo
        // 必须在这里的回调才能获取
        wx.onBLECharacteristicValueChange(function (characteristic) {
          console.log('characteristic');
          let str = ab2hex(characteristic.value)
          console.log(str);
        })

        wx.readBLECharacteristicValue({
          // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
          deviceId,
          // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
          serviceId,
          // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
          characteristicId: '0000FE50-0000-1000-8000-00805F9B34FB',
          success(res) {
            console.log('readBLECharacteristicValue:', res)
          }
        })
        // wx.notifyBLECharacteristicValueChange({
        //   state: true, // 启用 notify 功能
        //   // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
        //   deviceId,
        //   // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
        //   serviceId,
        //   // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
        //   characteristicId: '0000FE50-0000-1000-8000-00805F9B34FB',
        //   success (res) {
        //     console.log('notifynotifynotifynotify success', res.errMsg)
        //   },
        //   fail(res) {
        //     console.log('错误');
        //     console.log(res);
        //   }
        // })
        this.writeBLECharacteristicValue(dataInfo, 0)
      },
      fail(res) {
        console.error('getBLEDeviceCharacteristics', res)
      }
    })
    // 操作之前先监听，保证第一时间获取数据
    // wx.onBLECharacteristicValueChange((characteristic) => {
    //   const idx = inArray(this.data.chs, 'uuid', characteristic.characteristicId)
    //   const data = {}
    //   if (idx === -1) {
    //     data[`chs[${this.data.chs.length}]`] = {
    //       uuid: characteristic.characteristicId,
    //       value: ab2hex(characteristic.value)
    //     }
    //   } else {
    //     data[`chs[${idx}]`] = {
    //       uuid: characteristic.characteristicId,
    //       value: ab2hex(characteristic.value)
    //     }
    //   }
    //   // data[`chs[${this.data.chs.length}]`] = {
    //   //   uuid: characteristic.characteristicId,
    //   //   value: ab2hex(characteristic.value)
    //   // }
    //   console.log('data');
    //   console.log(data);
    //   this.setData(data)
    // })
  },
  writeBLECharacteristicValue(dataInfo, index) {
    let item = dataInfo[index]
    if (item) {
      // 将数据转换
      let byteData = new Uint8Array(item);
      //  let byteData = new Uint8Array([0x51,0x02]);
      let buffer = new ArrayBuffer(byteData.length);
      let dataView = new DataView(buffer);
      for (let i = 0; i < byteData.length; i++) {
        dataView.setUint8(i, byteData[i]);
      }
      // 开始写入到设备
      let _this = this
      wx.writeBLECharacteristicValue({
        deviceId: this.devMac,
        serviceId: '0000FEF0-0000-1000-8000-00805F9B34FB',
        characteristicId: '0000FE50-0000-1000-8000-00805F9B34FB',
        value: buffer,
        success(res) {
          console.log('发送数据包成功！', res);
          _this.writeBLECharacteristicValue(dataInfo, index += 1)
        },
        fail(res) {
          _this.errorResult('发送失败！')
          console.log(res);
          console.log(dataInfo);
          console.log(index);
        }
      })
    } else {
      this.successResult('发送成功！')
      this.closeBLEConnection()
      console.log('发送配网信息成功');
    }
  },
  closeBLEConnection() {
    wx.closeBLEConnection({
      deviceId: this.devMac
    })
  },
  formSubmit(e) {
    // 创建和蓝牙设备的连接
    this.data.serverInfo = e.detail.value
    if (this.serverInfpIsEmpty(this.data.serverInfo)) {
      // wifi信息
      let wifiName = this.wifiInfoToHex('50', this.data.serverInfo.wifiName)
      let wifiPwd = this.wifiInfoToHex('8B', this.data.serverInfo.wifiPwd)
      let wifi = wifiName + wifiPwd

      // 服务器信息
      let serverIp = this.data.serverInfo.serverIp
      let serverTCPPort = this.data.serverInfo.serverTcpPort
      // let serverHttpPort = this.data.serverInfo.serverHttpPort
      // let serverMask = this.data.serverInfo.serverMask
      let server = this.serverInfoToHex('CF', serverIp, serverTCPPort)

      // MQTT信息
      let MQTTIP = this.data.serverInfo.MQTTIP
      let MQTTClientId = this.data.serverInfo.MQTTClientId
      let MQTTTheme = this.data.serverInfo.MQTTTheme
      let MQTTUserName = this.data.serverInfo.MQTTUserName
      let MQTTPasswold = this.data.serverInfo.MQTTPasswold
      let MQTTPort = this.data.serverInfo.MQTTPort
      let MQTT = this.MQTTInfoToHex(MQTTIP, MQTTClientId, MQTTTheme, MQTTUserName, MQTTPasswold, MQTTPort)

      // 所有信息拼串
      let dataInfo = wifi + server + MQTT
      console.log('结果');
      console.log(dataInfo);
      console.log(dataInfo.length);
      let dataArr = this.formatConfigNetworkInfo(dataInfo)
      if (dataArr.length < 1) {
        return this.errorResult('输入有误，命令转换错误')
      }
      wx.setStorageSync('MQTTAndServerInfo', this.data.serverInfo)
      this.createBLEConnection(dataArr)
    }
  },
  wifiInfoToHex(head, str) {
    // 转换为UTF-8编码的字节数组
    let bytes = []
    for (let i = 0; i < str.length; i++) {
      let byte = str.charCodeAt(i);
      bytes.push(byte);
    }
    //  将字节数组转换为16进制字符串
    return head + bytes.map(byte => byte.toString(16)).join('').toUpperCase();
  },
  serverInfoToHex(head, serverIp, serverTCPPort) {
    let result = head
    // 转换服务器IP地址
    let splitServerIp = serverIp.split('.')
    splitServerIp.forEach(item => {
      // 获取当前IP段的十六进制的字符长度是否为1
      // 因为这里是直接把数字转换为十六进制，所以就要判断当前的十进制是不是其他小于9的数，因为十进制的0~9和十六进制的0~9是一样的
      let IpParagraph = Number(item).toString(16)
      if (IpParagraph.length === 1) {
        IpParagraph = '0' + IpParagraph
      }
      result += IpParagraph
    })
    // 转换tcp和http端口号
    result += Number(serverTCPPort).toString(16)
    return result.toUpperCase()
  },

  MQTTInfoToHex(MQTTIP, MQTTClientId, MQTTTheme, MQTTUserName, MQTTPasswold, MQTTPort) {
    let result = '0110'
    // 转换服务器IP地址
    let splitMQTTIP = MQTTIP.split('.')
    splitMQTTIP.forEach(item => {
      // 获取当前IP段的十六进制的字符长度是否为1
      // 因为这里是直接把数字转换为十六进制，所以就要判断当前的十进制是不是其他小于9的数，因为十进制的0~9和十六进制的0~9是一样的
      let IpParagraph = Number(item).toString(16)
      if (IpParagraph.length === 1) {
        IpParagraph = '0' + IpParagraph
      }
      result += IpParagraph
    })

    result += this.MQTTInfoToHex2('0150', MQTTClientId)
    result += this.MQTTInfoToHex2('0183', MQTTTheme)
    result += this.MQTTInfoToHex2('01C3', MQTTUserName)
    result += this.MQTTInfoToHex2('0203', MQTTPasswold)
    result += '0245' + Number(MQTTPort).toString(16)
    return result.toUpperCase()
  },

  MQTTInfoToHex2(head, str) {
    // 转换为UTF-8编码的字节数组
    let bytes = []
    for (let i = 0; i < str.length; i++) {
      let byte = str.charCodeAt(i);
      bytes.push(byte);
    }
    //  将字节数组转换为16进制字符串
    return head + bytes.map(byte => byte.toString(16)).join('').toUpperCase();
  },

  testResult() {
    /**
     * 0x50: wifi名称
     * 0x8B: wifi密码
     * 0xCF: 服务器IP、TCP端口、HTTP端口、子网掩码
     */
    let wifiName = this.wifiInfoToHex('50', 'TP-LINK_576F_17G')
    let wifiPwd = this.wifiInfoToHex('8B', 'alm12345678')
    let serverIp = '192.168.0.34'
    let serverTCPPort = '4476'
    let serverHttpPort = '4476'
    let serverMask = ''
    let server = this.data.serverInfoToHex('CF', serverIp, serverTCPPort, serverHttpPort, serverMask)
    console.log('结果');
    console.log(wifiName + wifiPwd + server);
  },
  serverInfpIsEmpty(obj) {
    console.log(obj);
    if (!obj.wifiName) {
      this.errorResult('WiFi名称为空')
      return false
    }
    if (!obj.wifiPwd) {
      this.errorResult('WiFi密码为空')
      return false
    }
    if (!obj.serverIp) {
      this.errorResult('服务器IP为空')
      return false
    } else {
      if (!this.ipFormatIsOk(obj.serverIp)) {
        this.errorResult('IP有误')
        return false
      }
    }
    if (!obj.serverTcpPort) {
      this.errorResult('TCP端口为空')
      return false
    } else {
      if (!isFinite(obj.serverTcpPort) || Number(obj.serverTcpPort) > 65536) {
        this.errorResult('TCP端口有误')
        return false
      }
    }
    
    if (!obj.MQTTIP) {
      this.errorResult('MQTT IP为空')
      return false
    } else {
      if (!this.ipFormatIsOk(obj.MQTTIP)) {
        this.errorResult('MQTT IP有误')
        return false
      }
    }

    if (!obj.MQTTClientId) {
      this.errorResult('客户端ID为空')
      return false
    }

    if (!obj.MQTTTheme) {
      this.errorResult('订阅为空')
      return false
    }

    if (!obj.MQTTUserName) {
      this.errorResult('用户名为空')
      return false
    }

    if (!obj.MQTTPasswold) {
      this.errorResult('密码为空')
      return false
    }

    if (!obj.MQTTPort) {
      this.errorResult('MQTT端口为空')
      return false
    } else {
      if (!isFinite(obj.MQTTPort) || Number(obj.MQTTPort) > 65536) {
        this.errorResult('MQTT端口有误')
        return false
      }
    }

    return true
  },
  errorResult(errorInfo) {
    wx.showToast({
      title: errorInfo,
      icon: 'error',
      duration: 2000
    })
  },
  successResult(successInfo) {
    wx.showToast({
      title: successInfo,
      icon: 'success',
      duration: 2000
    })
  },
  ipFormatIsOk(ip) {
    let splitIp = ip.split('.')
    for (let i = 0; i < splitIp.length; i++) {
      if (Number(splitIp[i]) > 255 || !isFinite(splitIp[i])) {
        return false
      }
    }
    return true
  },
  formatConfigNetworkInfo(configNetworkInfo) {
    // configNetworkInfo = '5054502D4C494E4B5F353736465F3137478B616C6D3132333435363738CF784E81E2117C117C'

    // 如果需要分包发送
    /**
     * 因为分包发送的头是 50 + (总包数 + 当前发送的第几包) ，然后后面跟着是要发送的配网数据
     * 但是设备每次只能发送20个字节，所以加上发送头的话，配网数据每次只能发18个字节
     * 示例: 50 30 意思就是，总包数是3包，当前发送的第1包。按照数组索引来表示
     */
    // 获取总包数
    let byteLen = configNetworkInfo.length / 2
    let allBackCount = parseInt(byteLen / 18)
    // 剩余字节数，因为是以十六进制来写的，一字节等于2位，所以要*2
    let residueByte = (byteLen - (18 * allBackCount)) * 2

    // 当前第n包的数据
    let sonBack = []
    // 配网数据总包
    let backCounts = []

    // 将总包数的配网数据写入
    for (let i = 0; i < allBackCount; i++) {
      for (let j = i * (18 * 2); j < (i + 1) * (18 * 2); j += 2) {
        var byte = parseInt(configNetworkInfo.substr(j, 2), 16);
        sonBack.push(byte);
      }
      backCounts.push(sonBack)
      sonBack = []
    }

    // 获取剩下的字节数
    for (let i = configNetworkInfo.length - residueByte; i < configNetworkInfo.length; i += 2) {
      var byte = parseInt(configNetworkInfo.substr(i, 2), 16);
      sonBack.push(byte);
    }
    backCounts.push(sonBack)

    // 给配网数据加上消息头
    for (let i = 0; i < backCounts.length; i++) {
      let item = backCounts[i]
      item.splice(0, 0, 0x50)
      item.splice(1, 0, parseInt(backCounts.length.toString() + i, 16))
    }
    console.log('格式化后的配网数据');
    console.log(backCounts);
    return backCounts
  },
  getLastTimeInputInfo() {
    let MQTTAndServerInfo = wx.getStorageSync('MQTTAndServerInfo')
    if (MQTTAndServerInfo) {
      for (var key in MQTTAndServerInfo) {
        if (MQTTAndServerInfo.hasOwnProperty(key)) {
          // console.log("属性: " + key + ", 值: " + MQTTAndServerInfo[key]);
          this.setData({
            [key]: MQTTAndServerInfo[key]
          })
        }
      }
    }
  }

})